/*
 * Galaxium Messenger
 * Copyright (C) 2008 Ben Motmans <ben.motmans@gmail.com>
 * 
 * License: GNU General Public License (GPL)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

using System;
using System.Text;
using System.Collections.Generic;

using Gtk;
using Gdk;
using GLib;

using Anculus.Core;

using Galaxium.Core;
using Galaxium.Gui;
using Galaxium.Gui.GtkGui;
using Galaxium.Client.GtkGui;

namespace Galaxium.Protocol.Irc.GtkGui
{
	public class IrcContactTreeManager : BasicContactTreeManager
	{
		public override void RenderText (object data, CellRendererContact renderer)
		{
			if (data is IrcContact)
				RenderContactText (data as IrcContact, renderer);
			else if (data is IrcChannel)
				RenderChannelText (data as IrcChannel, renderer);
			else
				base.RenderText (data, renderer);
		}
		
		public override void RenderLeftImage (object data, CellRendererPixbuf renderer)
		{
			if (!(data is AbstractContact)) {
				base.RenderLeftImage (data, renderer);
				return;
			}
			
			IConfigurationSection config = Configuration.ContactList.Section;
			AbstractContact contact = data as AbstractContact;
			ContactTreeDetailLevel detailLevel = contact.Session.Account.DetailLevel;
			
			if (contact.Session.Account.UseDefaultListView)
			{
				detailLevel = (ContactTreeDetailLevel)config.GetInt (Configuration.ContactList.DetailLevel.Name, Configuration.ContactList.DetailLevel.Default);
			}
			
			IIconSize iconSize = IconSizes.Other;

			switch (detailLevel)
			{
			case ContactTreeDetailLevel.Compact:
				iconSize = IconSizes.Small;
				break;
				
			case ContactTreeDetailLevel.Normal:
				iconSize = IconSizes.Medium;
				break;
				
			case ContactTreeDetailLevel.Detailed:
				iconSize = IconSizes.Large;
				break;
				
			default:
				// not currently dealing with this size.
				break;
			}
			
			if (data is IrcContact)
				RenderContactLeftImage (data as IrcContact, renderer, iconSize);
			else if (data is IrcChannel)
				RenderChannelLeftImage (data as IrcChannel, renderer, iconSize);
		}
		
		public override string GetMenuExtensionPoint (object data)
		{
			if (data is IrcContact)
				return "/Galaxium/Gui/IRC/ContactTree/ContextMenu/Contact";
			else if (data is IrcChannel)
				return "/Galaxium/Gui/IRC/ContactTree/ContextMenu/Channel";
			
			if (data is ContactTreeRealGroup)
				return "/Galaxium/Gui/IRC/ContactTree/ContextMenu/Group";
			
			return base.GetMenuExtensionPoint (data);
		}
		
		public override InfoTooltip GetTooltip (object data)
		{
			if (data is IrcContact)
				return new ContactListTooltip (data as IrcContact);
			
			return base.GetTooltip (data);
		}
		
		private void RenderContactText (IrcContact contact, CellRendererContact renderer)
		{
			StringBuilder sb = new StringBuilder ();
			ContactTreeDetailLevel detail = contact.Session.Account.DetailLevel;
			IConfigurationSection config = Configuration.ContactList.Section;
			
			if (contact.Session.Account.UseDefaultListView)
			{
				detail = (ContactTreeDetailLevel)config.GetInt (Configuration.ContactList.DetailLevel.Name, Configuration.ContactList.DetailLevel.Default);
			}
			
			sb.Append (Markup.EscapeText (contact.DisplayName));
			sb.Append (Environment.NewLine);
			
			if (detail != ContactTreeDetailLevel.Compact)
			{
				sb.AppendFormat ("<span foreground=\"#505050\" weight=\"light\" size=\"smaller\">{0}</span>", contact.Presence.State);
				sb.Append (Environment.NewLine);
			}
			
			renderer.ShowEmoticons = false;
			renderer.Markup = sb.ToString ();
		}
		
		private void RenderChannelText (IrcChannel channel, CellRendererContact renderer)
		{
			StringBuilder sb = new StringBuilder ();
			ContactTreeDetailLevel detail = channel.Session.Account.DetailLevel;
			IConfigurationSection config = Configuration.ContactList.Section;
			
			if (channel.Session.Account.UseDefaultListView)
			{
				detail = (ContactTreeDetailLevel)config.GetInt (Configuration.ContactList.DetailLevel.Name, Configuration.ContactList.DetailLevel.Default);
			}
			
			sb.Append (Markup.EscapeText (channel.DisplayName));
			
			if (detail == ContactTreeDetailLevel.Detailed)
			{
				sb.Append (Environment.NewLine);
				if (channel.Presence != IrcPresence.Offline)
				{
					if(channel.ContactCollection.Count == 1)
						sb.Append ("1 Contact");
					else
						sb.Append (channel.ContactCollection.Count + " Contacts");
				}
				else
					sb.Append (Markup.EscapeText ("Not joined"));
			}
			
			if (detail != ContactTreeDetailLevel.Compact)
			{
				sb.Append (Environment.NewLine);
				sb.Append ("<span foreground=\"#505050\" weight=\"light\" size=\"small\"><i>");
				
				if (channel.Presence != IrcPresence.Offline) {
					if (!String.IsNullOrEmpty (channel.Topic))
						sb.Append (Markup.EscapeText (channel.Topic));
					else
						sb.Append (Markup.EscapeText ("No topic is set"));
				}
							
				sb.Append ("</i></span>");
			}
			
			renderer.ShowEmoticons = false;
			renderer.Markup = sb.ToString ();
		}
		
		private void RenderContactLeftImage (IrcContact contact, CellRendererPixbuf renderer, IIconSize iconSize)
		{
			Pixbuf pixbuf = null;
			
			// Lets try and pull an activity from the queue
			IActivity activity = GtkActivityUtility.PeekContactQueueItem(contact);
			bool displayedActivity = false;
			
			if (iconSize == IconSizes.Small)
			{
				if (activity != null)
				{
					switch (activity.Type)
					{
						case ActivityTypes.Message:
							pixbuf = IconUtility.GetIcon ("galaxium-conversation-active", iconSize);
							displayedActivity = true;
							break;
						case ActivityTypes.Transfer:
							pixbuf = IconUtility.GetIcon ("galaxium-transfer-receive", iconSize);
							displayedActivity = true;
							break;
					}
				}
				else
				{
					pixbuf = IconUtility.StatusLookup (contact.Presence, iconSize);
				}
			}
			else
			{
				if (contact.Presence == IrcPresence.Offline)
					pixbuf = IconUtility.GetIcon ("galaxium-offline", iconSize);
				else
					pixbuf = IconUtility.GetIcon ("galaxium-contact", iconSize);
				
				// show overlay
				if (activity != null)
				{
					switch (activity.Type)
					{
						case ActivityTypes.Message:
							pixbuf = PixbufUtility.GetOverlayedRightPixbuf(pixbuf, IconUtility.GetIcon ("galaxium-conversation-active", IconSizes.Small));
							break;
						case ActivityTypes.Transfer:
							pixbuf = PixbufUtility.GetOverlayedRightPixbuf(pixbuf, IconUtility.GetIcon ("galaxium-transfer-receive", IconSizes.Small));
							break;
					}
				}
				else
				{
					if (contact.Presence != IrcPresence.Online)
						pixbuf = PixbufUtility.GetOverlayedRightPixbuf (pixbuf, IconUtility.StatusLookup (contact.Presence, IconSizes.Small));
				}
			}
			
			renderer.Pixbuf = pixbuf;
			renderer.Width = pixbuf.Width;
			renderer.Visible = true;
		}
		
		private void RenderChannelLeftImage (IrcChannel channel, CellRendererPixbuf renderer, IIconSize iconSize)
		{
			Pixbuf pixbuf = null;
			if (channel.Presence == IrcPresence.Offline)
				pixbuf = IconUtility.GetIcon ("irc-console-inactive", iconSize);
			else
			{
				IrcConversation conv = (channel.Session as IrcSession).ObtainConversation (channel, false);
				IActivity activity = GtkActivityUtility.PeekContactQueueItem(channel);
				bool displayedActivity = false;
				
				if (activity != null)
				{
					pixbuf = IconUtility.GetIcon ("irc-console-active", iconSize);
				}
				else
				{
					pixbuf = IconUtility.GetIcon ("irc-console", iconSize);
				}
			}
			
			renderer.Pixbuf = pixbuf;
			renderer.Width = pixbuf.Width;
			renderer.Visible = true;
		}
	}
}
